import os
import time
from impl.perf_stat.function_call import record_running_time


class DownloaderLock:
    def __init__(self, folder: str, expired_time):
        self.folder = folder
        self.expired_time = expired_time
        if not os.path.exists(folder):
            try:
                os.mkdir(folder)
            except OSError:
                pass

        self.locked = False

    def __enter__(self):
        if not self.locked:
            assert self.try_get_lock()

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.release_lock()

    def _get_lock_file(self):
        return os.path.join(self.folder, '.lock')

    def _try_create_lock_file(self):
        open_mode = os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_TRUNC
        try:
            fd = os.open(self._get_lock_file(), open_mode)
            os.close(fd)
            return True
        except OSError:
            return False

    def _try_get_lock(self):
        if self._try_create_lock_file():
            return True
        lock_file = self._get_lock_file()
        try:
            elapsed_time = time.time() - os.path.getmtime(lock_file)
            if elapsed_time < self.expired_time:
                return False
            else:
                os.remove(lock_file)
        except OSError:
            return False
        return self._try_create_lock_file()

    @record_running_time
    def try_get_lock(self):
        self.locked = self._try_get_lock()
        return self.locked

    @record_running_time
    def release_lock(self):
        try:
            os.remove(self._get_lock_file())
        except OSError:
            pass
